<script setup lang="ts">
import { ElMessage } from 'element-plus'
import type {
  EnergyDataReportList,
  ReportColumnsItem,
} from '../types'
import WrapComponent from './WrapComponent.vue'
import TableHead from './TableHead.vue'
import ReportPerson from './ReportPerson.vue'

import useInformant from './useInformant'
import useReportCell from './useReportCell'
import useArrowKey from './useArrowKey'

import { getFlatternColumns } from './util'
import {
  energyDiscountApi,
  energyMetrologicalReviewApi,
} from '@/api'
import { uuid } from '@/utils'

const props = defineProps<{
  dataTime: string
  readonly?: boolean
}>()
const title = ref('年度能源购进、消费与库存情况表')
const columns: ReportColumnsItem[] = [
  { label: '能源名称', prop: 'energyName' },
  { label: '计量单位', prop: 'unitOfMeasurement' },
  { label: '代码', prop: 'code' },
  { label: '期初库存量', prop: 'beginningInventory' },
  {
    label: '购进量',
    prop: 'E',
    children: [
      { label: '实物量', prop: 'physicalQuantity' },
      { label: '金额', prop: 'amount', unit: '千元' },
    ],
  },
  {
    label: '消费量',
    prop: 'F',
    children: [
      { label: '合计', prop: 'total' },
      {
        label: '工业生产消费',
        prop: 'industrialProduction',
      },
      { label: '用于原材料', prop: 'forRawMaterials' },
      {
        label: '非工业生产消费',
        prop: 'nonIndustrialProduction',
      },
      {
        label: '合计中:运输工具消费',
        prop: 'transportationConsumption',
      },
    ],
  },
  { label: '期末库存量', prop: 'endingInventory' },
  { label: '采用折标系数', prop: 'useScalingFactor' },
  { label: '参考折标系数', prop: 'referenceDiscountFactor' },
]
const flattenColumns = getFlatternColumns(columns)

const showLineNumber = ref(true)
const lists = ref<EnergyDataReportList[]>([
  ...Array(20)
    .fill(1)
    .map(() => ({
      uuid: uuid('temp_'),
      data: [
        ...flattenColumns.map(v => ({
          key: v.prop,
          value: '',
          editable: !props.readonly,
        })),
      ],
    })),
])

const { informant, setInformant } = useInformant()

// 消费量中的“合计"
const calc = computed(() => {
  const listsValue = lists.value.map(v => v.data)
  return listsValue.map((vv) => {
    const t1 = vv.find(
      x => x.key === 'industrialProduction',
    )
    const t2 = vv.find(
      x => x.key === 'nonIndustrialProduction',
    )
    if (t1 && t2) {
      return plus(t1?.value, t2?.value)
    }
    return ''
  })
})
function plus(a: number | string, b: number | string) {
  const isEmpty = (x: any) => x == null || x === ''
  if (isEmpty(a) || isEmpty(b))
    return ''
  const n = +(+a + +b).toFixed(2)
  return Number.isFinite(n) ? n : ''
}
const summary = computed(() => {
  const obj = {
    energyName: '能源合计',
    unitOfMeasurement: '',
    code: '40',
    referenceDiscountFactor: '',
  }
  const listsValue = lists.value.map(v => v.data)
  // 折标系数
  const sss = listsValue.map((v) => {
    const target = v.find(
      vv => vv.key === 'useScalingFactor',
    )
    return target ? target.value : ''
  })
  const props = flattenColumns.map(v => v.prop)
  const listsMap = props.reduce((acc, prop) => {
    if (
      ![
        'referenceDiscountFactor',
        'useScalingFactor',
      ].includes(prop)
    ) {
      acc[prop] = listsValue.map((v) => {
        const target = v.find(vv => vv.key === prop)
        return target ? target.value : ''
      })
    }
    return acc
  }, {} as any)

  // 消费量中的“合计"
  listsMap.total = [...calc.value]
  // ①期初库存合计=能源品种×采用折标系数（累加）；
  // ②实物量合计=上列数值累加；
  // ③金额合计=上列数值累加；
  // ④消费量：工业生产消费、用于原材料、非工业生产消费、合计中运输工具消费分别=能源品种×采用折标系数（累加）
  // 合计=工业生产消费累加值+非工业生产消费累计值；
  // ⑤期末库存合计=能源品种×采用折标系数（累加）。
  const accumulate = (prop: string, withFactor?: any) => {
    const n = +listsMap[prop]
      .reduce((acc: number, v: any, i: number) => {
        acc
          += (Number.isFinite(+v) ? +v : 0)
          * (withFactor ? +sss[i]! || 1 : 1)
        return acc
      }, 0)
      .toFixed(2)
    return Number.isFinite(n) ? n : ''
  }
  const getValue = (prop: string): any => {
    if (
      [
        'beginningInventory',
        'endingInventory',
        'industrialProduction',
        'forRawMaterials',
        'nonIndustrialProduction',
        'transportationConsumption',
      ].includes(prop)
    ) {
      // 期初库存量、期末库存合计
      // 工业生产消费、用于原材料、非工业生产消费、合计中运输工具消费
      return accumulate(prop, true)
    }
    else if (
      ['physicalQuantity', 'amount'].includes(prop)
    ) {
      // 实物量、金额
      return accumulate(prop)
    }
    else if (prop === 'total') {
      return plus(
        getValue('industrialProduction'),
        getValue('nonIndustrialProduction'),
      )
    }
  }

  const data = flattenColumns.map((v) => {
    let editable = true
    if (Object.keys(obj).includes(v.prop)) {
      editable = false
    }
    return {
      key: v.prop,
      // @ts-expect-error
      value: obj[v.prop] || getValue(v.prop),
      editable,
    }
  })

  return {
    uuid: uuid(),
    data,
  }
})
/**
 * 转换请求返回的数据为 lists
 * @param data
 */
function transfer(data: any) {
  const keys = flattenColumns.map(v => v.prop)
  return data.map((v: any) => {
    return {
      uuid: v.id || uuid('temp_'),
      data: keys.map((vv) => {
        const editable
          = ![
            'energyName',
            'unitOfMeasurement',
            'code',
            'total',
            'referenceDiscountFactor',
          ].includes(vv) && !props.readonly
        return {
          key: vv,
          value: String(v[vv] || ''),
          editable,
          calculable: vv === 'total',
        }
      }),
    }
  })
}

/**
 *
 * @override
 */
async function loadList() {
  let { data }
    = await energyMetrologicalReviewApi.loadYearEnergyConsumptionStructure(
      props.dataTime,
    )

  // 没数据的情况下查折标系数表作为空模板
  if (!data || data?.length === 0) {
    const res = await energyDiscountApi.queryList()
    try {
      data = res.data.map((v) => {
        return {
          id: v.id,
          energyName: v.name,
          unitOfMeasurement: (
            v.discountFactorUnit || ''
          ).split('/')[1],
          code: v.id,
          beginningInventory: null,
          amount: null,
          total: null,
          industrialProduction: null,
          forRawMaterials: null,
          nonIndustrialProduction: null,
          transportationConsumption: null,
          endingInventory: null,
          useScalingFactor: v.discountFactor,
          referenceDiscountFactor: v.referenceCoefficient,
        }
      })
    }
    catch (e) {}
  }

  const findIndex = data.findIndex(
    (v: any) =>
      v.energyName === '能源合计' || v.code === '40',
  )
  if (findIndex > -1) {
    data.splice(findIndex, 1)
  }

  const informantData = data.find((v: any) => v.type === 2)
  informantData && setInformant(informantData)

  // Set lists
  lists.value = transfer(data)
}

const dataTime
  = toValue(props.dataTime) || `${new Date().getFullYear()}`
function resolveLists(lists: Ref<EnergyDataReportList[]>) {
  const listsValue = toValue(lists)
  return listsValue.map((v, i) => {
    const data = v.data
    return {
      id: Number(v.uuid) || undefined,
      type: 1,
      dataTime,
      ...flattenColumns.reduce((acc, vv, ii) => {
        const useCalc = vv.prop === 'total'
        acc[vv.prop] = useCalc
          ? toValue(calc)[i]
          : data[ii].value
        return acc
      }, {} as any),
    }
  })
}
async function saveStage() {
  const list = [...resolveLists(lists)]

  list.push({
    type: 2,
    dataTime,
    ...toValue(informant),
  })

  await energyMetrologicalReviewApi.saveOrUpdateEnergyConsumptionStructure(
    list,
  )
  ElMessage.success('保存成功')
}

const { inputIndex, initInputIndex, clickCallback }
  = useReportCell()
useArrowKey(inputIndex, flattenColumns.length)

async function init() {
  // 接口将废弃
  // await loadList();
  initInputIndex()
}

onMounted(() => {
  init()
})
</script>

<template>
  <WrapComponent>
    <template v-if="$slots.title" #title>
      <slot
        name="title"
        :title="title"
        :save-stage="saveStage"
      />
    </template>
    <div class="width-fill height-fill flex-direction flex">
      <div class="report-table-head">
        <table class="report-table">
          <TableHead
            :columns="columns"
            :show-line-number="showLineNumber"
          />
        </table>
      </div>
      <ElScrollbar>
        <table class="report-table">
          <tbody ref="tbody">
            <tr v-for="(item, i) in lists" :key="item.uuid">
              <th
                v-if="showLineNumber"
                class="readonly width-40px line-number"
              >
                {{ i + 1 }}
              </th>
              <td
                v-for="(d, index) in item.data"
                :key="`${item.uuid}_${index}`"
                :class="{ 'is-calculable': d.calculable }"
              >
                <div v-if="!d.editable" class="span-cell">
                  {{ d.calculable ? calc[i] : d.value }}
                </div>
                <div v-else class="input-cell">
                  <input
                    v-model="d.value"
                    type="text"
                    @click="clickCallback"
                  >
                </div>
              </td>
            </tr>
            <tr class="readonly">
              <th
                v-if="showLineNumber"
                class="readonly width-40px line-number"
              >
                {{ lists.length + 1 }}
              </th>
              <td
                v-for="(item, index) in summary.data"
                :key="summary.uuid + index"
              >
                <div class="span-cell">
                  {{ item.value }}
                </div>
              </td>
            </tr>
          </tbody>
        </table>
        <div class="description-text">
          <p>说明：</p>
          <p>1．主要逻辑审核关系：</p>
          <p class="padding-horizontal">
            (1) 消费合计=工业生产消费+非工业生产消费。
          </p>
          <p class="padding-horizontal">
            (2) 工业生产消费≥用于原材料。
          </p>
          <p class="padding-horizontal">
            (3) 消费合计≥运输工具消费。
          </p>
          <p>
            2．企业只填写本企业消耗的有关能源品种数值。如本表未包括企业消耗的能源品种，企业应根据统计部门要求归并入相应能源品种内。
          </p>
          <p>
            3．能源合计=∑某种能源×某种能源折标准煤系数（不重复计算“其中”项）。
          </p>
          <p>4．综合能源消费量的计算方法：</p>
          <p class="padding-horizontal">
            (1)非能源加工转换企业：综合能源消费量=工业生产消费的能源折标量合计-回收利用折标量合计（表1-2-1中第13列）。
          </p>
          <p class="padding-horizontal">
            (2)能源加工转换企业：综合能源消费量=工业生产消费的能源折标量合计-能源加工转换产出折标量合计（表1-2-1中第12列）-回收利用折标量合计（表1-2-1中第13列）。
          </p>
        </div>
      </ElScrollbar>
      <ReportPerson
        v-model="informant"
        :readonly="readonly"
      />
    </div>
  </WrapComponent>
</template>
